/*
* Copyright (c) 2002-2015, Mairie de Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.portal.web.user;
import fr.paris.lutece.portal.business.user.AdminUser;
import fr.paris.lutece.portal.business.user.AdminUserHome;
import fr.paris.lutece.portal.business.user.authentication.LuteceDefaultAdminUser;
import fr.paris.lutece.portal.business.user.log.UserLog;
import fr.paris.lutece.portal.business.user.log.UserLogHome;
import fr.paris.lutece.portal.business.user.parameter.DefaultUserParameterHome;
import fr.paris.lutece.portal.service.admin.AdminAuthenticationService;
import fr.paris.lutece.portal.service.admin.AdminUserService;
import fr.paris.lutece.portal.service.i18n.I18nService;
import fr.paris.lutece.portal.service.init.AppInfo;
import fr.paris.lutece.portal.service.mail.MailService;
import fr.paris.lutece.portal.service.message.AdminMessage;
import fr.paris.lutece.portal.service.message.AdminMessageService;
import fr.paris.lutece.portal.service.portal.PortalService;
import fr.paris.lutece.portal.service.spring.SpringContextService;
import fr.paris.lutece.portal.service.template.AppTemplateService;
import fr.paris.lutece.portal.service.util.AppHTTPSService;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPathService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.portal.web.constants.Messages;
import fr.paris.lutece.portal.web.constants.Parameters;
import fr.paris.lutece.portal.web.l10n.LocaleService;
import fr.paris.lutece.util.ReferenceList;
import fr.paris.lutece.util.html.HtmlTemplate;
import fr.paris.lutece.util.http.SecurityUtil;
import fr.paris.lutece.util.password.IPasswordFactory;
import fr.paris.lutece.util.string.StringUtil;
import fr.paris.lutece.util.url.UrlItem;
import org.apache.commons.lang.StringUtils;
import java.io.Serializable;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* This class provides the user interface to manage login features ( login, logout, ... )
*/
public class AdminLoginJspBean implements Serializable
{
/**
* Serial version UID
*/
private static final long serialVersionUID = 1437296329596757569L;
// //////////////////////////////////////////////////////////////////////////
// Constants
private static final String CONSTANT_EMAIL_DELIMITER = ";";
private static final String CONSTANT_EMPTY_STRING = "";
private static final String CONSTANT_SLASH = "/";
private static final String CONSTANT_HTTP = "http";
private static final String REGEX_ID = "^[\\d]+$";
// Jsp
private static final String JSP_URL_MODIFY_DEFAULT_USER_PASSOWRD = "jsp/admin/user/ModifyDefaultUserPassword.jsp";
private static final String JSP_URL_FORM_CONTACT = "AdminFormContact.jsp";
private static final String JSP_URL_DO_ADMIN_LOGIN = "jsp/admin/DoAdminLogin.jsp";
private static final String JSP_URL_ADMIN_LOGIN = "jsp/admin/AdminLogin.jsp";
// Templates
private static final String TEMPLATE_ADMIN_LOGIN = "admin/admin_login.html";
private static final String TEMPLATE_ADMIN_FORGOT_PASSWORD = "admin/admin_forgot_password.html";
private static final String TEMPLATE_ADMIN_FORGOT_LOGIN = "admin/admin_forgot_login.html";
private static final String TEMPLATE_ADMIN_FORM_CONTACT = "admin/admin_form_contact.html";
private static final String TEMPLATE_ADMIN_EMAIL_FORGOT_PASSWORD = "admin/admin_email_forgot_password.html";
private static final String TEMPLATE_ADMIN_EMAIL_FORGOT_LOGIN = "admin/admin_email_forgot_login.html";
// Markers
private static final String MARK_PARAMS_LIST = "params_list";
private static final String MARK_FORGOT_PASSWORD_URL = "forgot_password_url";
private static final String MARK_FORGOT_LOGIN_URL = "forgot_login_url";
private static final String MARK_PARAM_VERSION = "version";
private static final String MARK_SITE_NAME = "site_name";
private static final String MARK_NEW_PASSWORD = "new_password";
private static final String MARK_LOGIN_URL = "login_url";
private static final String MARK_DO_ADMIN_LOGIN_URL = "do_admin_login_url";
private static final String MARK_SITE_LINK = "site_link";
private static final String MARK_LOGIN = "login";
private static final String SESSION_ATTRIBUTE_USER = "lutece_admin_user"; // Used by all JSP
// parameters
private static final String PARAMETER_MESSAGE = "message_contact";
private static final String PARAMETER_FORCE_CHANGE_PASSWORD_REINIT = "force_change_password_reinit";
// I18n message keys
private static final String MESSAGE_SENDING_SUCCESS = "portal.admin.message.admin_forgot_password.sendingSuccess";
private static final String MESSAGE_ADMIN_SENDING_SUCCESS = "portal.admin.message.admin_form_contact.sendingSuccess";
private static final String MESSAGE_EMAIL_SUBJECT = "portal.admin.admin_forgot_password.email.subject";
private static final String MESSAGE_FORGOT_LOGIN_EMAIL_SUBJECT = "portal.admin.admin_forgot_login.email.subject";
private static final String MESSAGE_FORGOT_LOGIN_SENDING_SUCCESS = "portal.admin.message.admin_forgot_login.sendingSuccess";
private static final String MESSAGE_EMAIL_ADMIN_SUBJECT = "portal.admin.admin_form_contact.email.subject";
private static final String MESSAGE_WRONG_EMAIL_FORMAT = "portal.admin.message.admin_forgot_login.wrongEmailFormat";
// Properties
private static final String PROPERTY_LEVEL = "askPasswordReinitialization.admin.level";
/**
* Returns the view of login form
*
* @param request
* The request
* @return The HTML form
*/
public String getLogin( HttpServletRequest request )
{
HashMap<String, Object> model = new HashMap<String, Object>( );
// Invalidate a previous session
HttpSession session = request.getSession( );
if ( session != null )
{
session.removeAttribute( SESSION_ATTRIBUTE_USER );
// Put real base url in session
request.getSession( ).setAttribute( AppPathService.SESSION_BASE_URL, AppPathService.getBaseUrl( request ) );
}
Locale locale = AdminUserService.getLocale( request );
Enumeration<String> enumParams = request.getParameterNames( );
ReferenceList listParams = new ReferenceList( );
String strParamName;
while ( enumParams.hasMoreElements( ) )
{
strParamName = enumParams.nextElement( );
String strParamValue = request.getParameter( strParamName );
listParams.addItem( strParamName, strParamValue );
}
StringBuilder sbUrl = new StringBuilder( );
if ( AppHTTPSService.isHTTPSSupportEnabled( ) )
{
sbUrl.append( AppHTTPSService.getHTTPSUrl( request ) );
}
else
{
sbUrl.append( AppPathService.getBaseUrl( request ) );
}
if ( !sbUrl.toString( ).endsWith( CONSTANT_SLASH ) )
{
sbUrl.append( CONSTANT_SLASH );
}
sbUrl.append( JSP_URL_DO_ADMIN_LOGIN );
model.put( MARK_PARAM_VERSION, AppInfo.getVersion( ) );
model.put( MARK_SITE_NAME, PortalService.getSiteName( ) );
model.put( MARK_PARAMS_LIST, listParams );
model.put( MARK_FORGOT_PASSWORD_URL, AdminAuthenticationService.getInstance( ).getLostPasswordPageUrl( ) );
model.put( MARK_FORGOT_LOGIN_URL, AdminAuthenticationService.getInstance( ).getLostLoginPageUrl( ) );
model.put( MARK_DO_ADMIN_LOGIN_URL, sbUrl.toString( ) );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_LOGIN, locale, model );
return template.getHtml( );
}
/**
* Returns the view of forgot password form
*
* @param request
* The request
* @return The HTML form
*/
public String getForgotPassword( HttpServletRequest request )
{
Map<String, Object> model = new HashMap<String, Object>( );
// Invalidate a previous session
HttpSession session = request.getSession( );
if ( session != null )
{
session.removeAttribute( SESSION_ATTRIBUTE_USER );
}
Locale locale = AdminUserService.getLocale( request );
Enumeration<String> enumParams = request.getParameterNames( );
ReferenceList listParams = new ReferenceList( );
String strParamName;
while ( enumParams.hasMoreElements( ) )
{
strParamName = enumParams.nextElement( );
String strParamValue = request.getParameter( strParamName );
listParams.addItem( strParamName, strParamValue );
}
model.put( MARK_PARAM_VERSION, AppInfo.getVersion( ) );
model.put( MARK_PARAMS_LIST, listParams );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_FORGOT_PASSWORD, locale, model );
return template.getHtml( );
}
/**
* Returns the view of forgot password form
*
* @param request
* The request
* @return The HTML form
*/
public String getForgotLogin( HttpServletRequest request )
{
Map<String, Object> model = new HashMap<String, Object>( );
// Invalidate a previous session
HttpSession session = request.getSession( );
if ( session != null )
{
session.removeAttribute( SESSION_ATTRIBUTE_USER );
}
Locale locale = AdminUserService.getLocale( request );
Enumeration<String> enumParams = request.getParameterNames( );
ReferenceList listParams = new ReferenceList( );
String strParamName;
while ( enumParams.hasMoreElements( ) )
{
strParamName = enumParams.nextElement( );
String strParamValue = request.getParameter( strParamName );
listParams.addItem( strParamName, strParamValue );
}
model.put( MARK_PARAM_VERSION, AppInfo.getVersion( ) );
model.put( MARK_PARAMS_LIST, listParams );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_FORGOT_LOGIN, locale, model );
return template.getHtml( );
}
/**
* Get the admin contact form
*
* @param request
* The Http request
* @return The HTML form
*/
public String getFormContact( HttpServletRequest request )
{
HashMap<String, Object> model = new HashMap<String, Object>( );
// Invalidate a previous session
HttpSession session = request.getSession( );
if ( session != null )
{
session.removeAttribute( SESSION_ATTRIBUTE_USER );
}
Locale locale = AdminUserService.getLocale( request );
model.put( MARK_PARAM_VERSION, AppInfo.getVersion( ) );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_FORM_CONTACT, locale, model );
return template.getHtml( );
}
/**
* Process the login of user
*
* @param request
* The HTTP Request
* @return The Jsp URL of the process result
* @throws Exception
* The exception
*/
public String doLogin( HttpServletRequest request ) throws Exception
{
if ( request.getScheme( ).equals( CONSTANT_HTTP ) && AppHTTPSService.isHTTPSSupportEnabled( ) )
{
return JSP_URL_ADMIN_LOGIN;
}
// recovery of the login attributes
String strAccessCode = request.getParameter( Parameters.ACCESS_CODE );
String strPassword = request.getParameter( Parameters.PASSWORD );
if ( strAccessCode == null || strPassword == null )
{
// TIME RESISTANT ATTACK
// Computation time is equal to the time needed by a legitimate user
strAccessCode = "";
strPassword = "";
}
String strLoginUrl = AdminAuthenticationService.getInstance( ).getLoginPageUrl( );
try
{
AdminAuthenticationService.getInstance( ).loginUser( request, strAccessCode, strPassword );
}
catch( FailedLoginException ex )
{
// Creating a record of connections log
UserLog userLog = new UserLog( );
userLog.setAccessCode( strAccessCode );
userLog.setIpAddress( SecurityUtil.getRealIp( request ) );
userLog.setDateLogin( new java.sql.Timestamp( new java.util.Date( ).getTime( ) ) );
userLog.setLoginStatus( UserLog.LOGIN_DENIED ); // will be inserted only if access denied
UserLogHome.addUserLog( userLog );
return AdminMessageService.getMessageUrl( request, Messages.MESSAGE_AUTH_FAILURE, strLoginUrl, AdminMessage.TYPE_STOP );
}
catch( LoginException ex )
{
AppLogService.error( "Error during connection for user access code :" + strAccessCode, ex );
return AdminMessageService.getMessageUrl( request, Messages.MESSAGE_AUTH_FAILURE, strLoginUrl, AdminMessage.TYPE_STOP );
}
UrlItem url;
AdminUser user = AdminUserHome.findUserByLogin( strAccessCode );
if ( user.isPasswordReset( ) )
{
String strRedirectUrl = AdminMessageService.getMessageUrl( request, Messages.MESSAGE_USER_MUST_CHANGE_PASSWORD,
JSP_URL_MODIFY_DEFAULT_USER_PASSOWRD, AdminMessage.TYPE_ERROR );
url = new UrlItem( strRedirectUrl );
}
else
{
String strNextUrl = AdminAuthenticationService.getInstance( ).getLoginNextUrl( request );
if ( StringUtils.isNotBlank( strNextUrl ) )
{
url = new UrlItem( strNextUrl );
}
else
{
url = AppPathService.resolveRedirectUrl( request, AppPathService.getAdminMenuUrl( ) );
}
}
return url.getUrl( );
}
/**
* Process the sending to user password
*
* @param request
* The HTTP Request
* @return The Jsp URL of the process result
* @throws Exception
* The exception
*/
public String doForgotPassword( HttpServletRequest request ) throws Exception
{
// get mail from user
String strAccessCode = request.getParameter( Parameters.ACCESS_CODE );
Locale locale = AdminUserService.getLocale( request );
if ( StringUtils.isEmpty( strAccessCode ) )
{
return AdminMessageService.getMessageUrl( request, Messages.MANDATORY_FIELDS, AdminMessage.TYPE_STOP );
}
if ( locale == null )
{
locale = LocaleService.getDefault( );
}
// if user or mail not found, send admin message
AdminUser user = AdminUserHome.findUserByLogin( strAccessCode );
if ( ( user == null ) || StringUtils.isEmpty( user.getEmail( ) ) )
{
return JSP_URL_FORM_CONTACT;
}
// make password
String strPassword = AdminUserService.makePassword( );
// update password
if ( StringUtils.isNotEmpty( strPassword ) )
{
LuteceDefaultAdminUser userStored = AdminUserHome.findLuteceDefaultAdminUserByPrimaryKey( user.getUserId( ) );
userStored.setPasswordMaxValidDate( AdminUserService.getPasswordMaxValidDate( ) );
IPasswordFactory passwordFactory = SpringContextService.getBean( IPasswordFactory.BEAN_NAME );
userStored.setPassword( passwordFactory.getPasswordFromCleartext( strPassword ) );
if ( Boolean.valueOf( DefaultUserParameterHome.findByKey( PARAMETER_FORCE_CHANGE_PASSWORD_REINIT ) ) )
{
userStored.setPasswordReset( Boolean.TRUE );
}
AdminUserHome.update( userStored );
}
// send password by e-mail
String strSenderEmail = MailService.getNoReplyEmail( );
String strEmailSubject = I18nService.getLocalizedString( MESSAGE_EMAIL_SUBJECT, locale );
HashMap<String, Object> model = new HashMap<String, Object>( );
model.put( MARK_NEW_PASSWORD, strPassword );
model.put( MARK_LOGIN_URL, AppPathService.getBaseUrl( request ) + AdminAuthenticationService.getInstance( ).getLoginPageUrl( ) );
model.put( MARK_SITE_LINK, MailService.getSiteLink( AppPathService.getBaseUrl( request ), false ) );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_EMAIL_FORGOT_PASSWORD, locale, model );
MailService.sendMailHtml( user.getEmail( ), strSenderEmail, strSenderEmail, strEmailSubject, template.getHtml( ) );
return AdminMessageService.getMessageUrl( request, MESSAGE_SENDING_SUCCESS, JSP_URL_ADMIN_LOGIN, AdminMessage.TYPE_INFO );
}
/**
* Process the sending of the login
*
* @param request
* The HTTP Request
* @return The Jsp URL of the process result
* @throws Exception
* The exception
*/
public String doForgotLogin( HttpServletRequest request ) throws Exception
{
String strEmail = request.getParameter( Parameters.EMAIL );
Locale locale = AdminUserService.getLocale( request );
if ( ( strEmail == null ) || strEmail.equals( CONSTANT_EMPTY_STRING ) )
{
return AdminMessageService.getMessageUrl( request, Messages.MANDATORY_FIELDS, AdminMessage.TYPE_STOP );
}
if ( !AdminUserService.checkEmail( strEmail ) )
{
return AdminMessageService.getMessageUrl( request, MESSAGE_WRONG_EMAIL_FORMAT, AdminMessage.TYPE_STOP );
}
if ( locale == null )
{
locale = LocaleService.getDefault( );
}
// if access code not found, send admin message
String strAccessCode = AdminUserHome.findUserByEmail( strEmail );
if ( StringUtils.isEmpty( strAccessCode ) )
{
return JSP_URL_FORM_CONTACT;
}
// send access code by e-mail
String strSenderEmail = MailService.getNoReplyEmail( );
String strEmailSubject = I18nService.getLocalizedString( MESSAGE_FORGOT_LOGIN_EMAIL_SUBJECT, locale );
HashMap<String, Object> model = new HashMap<String, Object>( );
model.put( MARK_LOGIN, strAccessCode );
model.put( MARK_LOGIN_URL, AppPathService.getBaseUrl( request ) + AdminAuthenticationService.getInstance( ).getLoginPageUrl( ) );
model.put( MARK_SITE_LINK, MailService.getSiteLink( AppPathService.getBaseUrl( request ), false ) );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_EMAIL_FORGOT_LOGIN, locale, model );
MailService.sendMailHtml( strEmail, strSenderEmail, strSenderEmail, strEmailSubject, template.getHtml( ) );
return AdminMessageService.getMessageUrl( request, MESSAGE_FORGOT_LOGIN_SENDING_SUCCESS, AdminMessage.TYPE_INFO );
}
/**
* Send the message to the adminsitrator(s)
*
* @param request
* The {@link HttpServletRequest}
* @return an adminMessage
*/
public String doFormContact( HttpServletRequest request )
{
// Get message, check if empty
String strMessage = request.getParameter( PARAMETER_MESSAGE );
if ( ( strMessage == null ) || strMessage.equals( CONSTANT_EMPTY_STRING ) )
{
return AdminMessageService.getMessageUrl( request, Messages.MANDATORY_FIELDS, AdminMessage.TYPE_STOP );
}
Locale locale = AdminUserService.getLocale( request );
if ( locale == null )
{
locale = LocaleService.getDefault( );
}
// send mail to admin wich have level
int nIdLevel = 0;
String strLevelId = AppPropertiesService.getProperty( PROPERTY_LEVEL, "0" );
if ( ( strLevelId != null ) && strLevelId.matches( REGEX_ID ) )
{
nIdLevel = Integer.parseInt( strLevelId );
}
Collection<AdminUser> adminUserList = AdminUserHome.findByLevel( nIdLevel );
StringBuilder sbMailsTo = new StringBuilder( CONSTANT_EMPTY_STRING );
for ( AdminUser adminUser : adminUserList )
{
if ( StringUtil.checkEmail( adminUser.getEmail( ) ) )
{
sbMailsTo.append( adminUser.getEmail( ) ).append( CONSTANT_EMAIL_DELIMITER );
}
}
String strMailsTo = sbMailsTo.toString( );
if ( !strMailsTo.equals( CONSTANT_EMPTY_STRING ) )
{
String strSenderEmail = MailService.getNoReplyEmail( );
String strEmailSubject = I18nService.getLocalizedString( MESSAGE_EMAIL_ADMIN_SUBJECT, locale );
MailService.sendMailHtml( strMailsTo, strSenderEmail, strSenderEmail, strEmailSubject, strMessage );
}
return AdminMessageService.getMessageUrl( request, MESSAGE_ADMIN_SENDING_SUCCESS, AdminAuthenticationService.getInstance( ).getLoginPageUrl( ),
AdminMessage.TYPE_INFO );
}
/**
* Process the logout of user
*
* @param request
* Http request
* @return The Jsp URL of the process result
*/
public String doLogout( HttpServletRequest request )
{
// Invalidation of the session
HttpSession session = request.getSession( );
if ( session != null )
{
session.invalidate( );
}
String strLoginUrl = AdminAuthenticationService.getInstance( ).getLoginPageUrl( );
return AdminMessageService.getMessageUrl( request, Messages.MESSAGE_LOGOUT, strLoginUrl, AdminMessage.TYPE_INFO );
}
}